#include "FaceRecognition.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QSysInfo>
#include <QThread>

FaceRecognition &FaceRecognition::getInstance()
{
    static FaceRecognition instance;
    return instance;
}

FaceRecognition::FaceRecognition(QObject *parent) : QObject(parent)
{
    QString appDir = QCoreApplication::applicationDirPath();
    if (QSysInfo::productType() == "windows")
    {
        setExecutablePath(
            QString("%1/python_path/python.exe \"%1/face_recognition_script.py\"").arg(appDir),
            QString("%1/python_path/python.exe \"%1/face_recognition_script_alone.py\"")
                .arg(appDir));
    }
    else
    {
        setExecutablePath(
            QString("%1/python_path/bin/python \"%1/face_recognition_script.py\"").arg(appDir),
            QString("%1/python_path/bin/python \"%1/face_recognition_script_alone.py\"")
                .arg(appDir));
    }

    // 初始化m_currentProcess为nullptr
    m_currentProcess = nullptr;
}

FaceRecognition::~FaceRecognition()
{
    stopProcess();
    qDebug() << "FaceRecognition::~FaceRecognition()";
    if (m_currentProcess)
    {
        m_currentProcess->disconnect();
        m_currentProcess->terminate();
        if (!m_currentProcess->waitForFinished(3000))
        {
            m_currentProcess->kill();
        }
        delete m_currentProcess;
        m_currentProcess = nullptr;
    }
    qDebug() << "FaceRecognition::~FaceRecognition() end";
}

void FaceRecognition::setExecutablePath(const QString &batchPath, const QString &singlePath)
{
    QMutexLocker locker(&mutex);
    m_batchExecPath  = batchPath;
    m_singleExecPath = singlePath;
}

void FaceRecognition::appendOutput(const QString &text)
{
    if (m_outputWidget && !text.isEmpty())
    {
        m_outputWidget->append(text.trimmed());
        m_outputWidget->ensureCursorVisible();
    }
}

// symbol 为 true 时，表示 生成未知人脸文件 ，否则为只识别已知人脸
QString FaceRecognition::runFaceRecognition(bool symbol, const QString &knownFacesDir,
                                            const QString &checkImagesDir,
                                            const QString &outputJsonPath, int cpus,
                                            double tolerance, bool showDistance)
{
    QMutexLocker locker(&mutex);
    m_lastOutput.clear();

    try
    {
        // 检查目录
        QDir knownDir(knownFacesDir);
        if (!knownDir.exists() && !knownDir.mkpath("."))
        {
            QString error = QString("错误：无法创建人脸库目录 %1").arg(knownFacesDir);
            appendOutput(error);
            return error;
        }

        QFileInfo checkPathInfo(checkImagesDir);
        if (!checkPathInfo.exists())
        {
            if (checkPathInfo.suffix().isEmpty())
            {
                QDir checkDir(checkImagesDir);
                if (!checkDir.mkpath("."))
                {
                    QString error = QString("错误：无法创建检查图片目录 %1").arg(checkImagesDir);
                    appendOutput(error);
                    return error;
                }
            }
            else
            {
                QString error = QString("错误：检查图片文件不存在 %1").arg(checkImagesDir);
                appendOutput(error);
                return error;
            }
        }

        // 清理旧进程
        if (m_currentProcess)
        {
            m_currentProcess->disconnect();
            m_currentProcess->terminate();
            if (!m_currentProcess->waitForFinished(3000))
            {
                m_currentProcess->kill();
            }
            delete m_currentProcess;
        }

        // 创建新进程
        m_currentProcess = new QProcess(this);
        if (!m_currentProcess)
        {
            QString error = "错误：无法创建进程";
            appendOutput(error);
            return error;
        }

        // 设置工作目录
        m_currentProcess->setWorkingDirectory(QCoreApplication::applicationDirPath());

        // 准备命令
        QString execPath     = symbol ? m_batchExecPath : m_singleExecPath;
        QStringList cmdParts = execPath.split(" ");
        QString pythonPath   = cmdParts.first();
        QString scriptPath   = cmdParts.mid(1).join(" ").replace("\"", "");

        QStringList arguments;
        arguments << scriptPath << "--cpus" << QString::number(cpus) << "--tolerance"
                  << QString::number(tolerance) << "--show-distance"
                  << (showDistance ? "true" : "false") << knownFacesDir << checkImagesDir;

        QString cmdLine = pythonPath + " " + arguments.join(" ");
        appendOutput("执行命令: " + cmdLine);
        m_lastOutput = "执行命令: " + cmdLine + "\n";

        // 启动进程
        m_currentProcess->start(pythonPath, arguments);

        // 等待启动
        if (!m_currentProcess->waitForStarted(3000))
        {
            QString error = "进程启动失败: " + m_currentProcess->errorString();
            appendOutput(error);
            m_lastOutput += error + "\n";
            return m_lastOutput;
        }

        // 读取输出
        while (m_currentProcess->state() != QProcess::NotRunning)
        {
            // 处理所有待处理的事件，确保UI更新
            QCoreApplication::processEvents();

            if (m_currentProcess->waitForReadyRead(100))
            {
                QByteArray output = m_currentProcess->readAllStandardOutput();
                if (!output.isEmpty())
                {
                    QString text = QString::fromUtf8(output).trimmed();
                    if (!text.isEmpty())
                    {
                        appendOutput(text);
                        m_lastOutput += text + "\n";
                        // 再次处理事件，确保输出立即显示
                        QCoreApplication::processEvents();
                    }
                }

                QByteArray error = m_currentProcess->readAllStandardError();
                if (!error.isEmpty())
                {
                    QString text = QString::fromUtf8(error).trimmed();
                    if (!text.isEmpty())
                    {
                        appendOutput(text);
                        m_lastOutput += text + "\n";
                        // 再次处理事件，确保输出立即显示
                        QCoreApplication::processEvents();
                    }
                }
            }

            // 短暂休眠，避免CPU占用过高
            QThread::msleep(10);
        }

        // 确保读取所有剩余输出
        while (m_currentProcess->bytesAvailable() > 0 || m_currentProcess->bytesAvailable() > 0)
        {
            QCoreApplication::processEvents();

            QByteArray output = m_currentProcess->readAllStandardOutput();
            if (!output.isEmpty())
            {
                QString text = QString::fromUtf8(output).trimmed();
                if (!text.isEmpty())
                {
                    appendOutput(text);
                    m_lastOutput += text + "\n";
                }
            }

            QByteArray error = m_currentProcess->readAllStandardError();
            if (!error.isEmpty())
            {
                QString text = QString::fromUtf8(error).trimmed();
                if (!text.isEmpty())
                {
                    appendOutput(text);
                    m_lastOutput += text + "\n";
                }
            }

            QThread::msleep(10);
        }

        // 检查退出状态
        if (m_currentProcess->exitCode() != 0)
        {
            QString error = QString("进程退出代码: %1").arg(m_currentProcess->exitCode());
            appendOutput(error);
            m_lastOutput += error + "\n";
        }
    }
    catch (const std::exception &e)
    {
        QString error = QString("发生异常: %1").arg(e.what());
        appendOutput(error);
        m_lastOutput = error;
    }
    catch (...)
    {
        QString error = "发生未知异常";
        appendOutput(error);
        m_lastOutput = error;
    }

    return m_lastOutput;
}

void FaceRecognition::stopProcess()
{
    if (m_currentProcess)
    {
        qDebug() << "正在停止人脸识别进程...";
        m_currentProcess->disconnect();
        m_currentProcess->terminate();
        
        // 等待进程终止，最多等待3秒
        if (!m_currentProcess->waitForFinished(3000))
        {
            qDebug() << "进程未能正常终止，强制结束";
            m_currentProcess->kill();
        }
        
        delete m_currentProcess;
        m_currentProcess = nullptr;
        qDebug() << "人脸识别进程已停止";
    }
}
